/**
 * 安全的 setData 包装函数
 * 专门为微信小程序设计，防止 updateTextView 32776 错误
 */

import errorMonitoring from './errorMonitoring.js'
import lifecycleManager from './componentLifecycle.js'

class SafeSetDataWrapper {
  constructor() {
    this.updateQueue = new Map()
    this.isProcessing = false
    this.batchTimeout = null
    this.batchDelay = 16 // 16ms，约等于一帧的时间
    this.maxBatchSize = 20
  }

  /**
   * 安全的 setData 方法
   * @param {Object} component - 小程序页面/组件实例
   * @param {Object} data - 要设置的数据
   * @param {Function} callback - 回调函数
   * @param {Object} options - 配置选项
   */
  safeSetData(component, data, callback, options = {}) {
    const config = {
      immediate: false,
      batch: true,
      validate: true,
      retry: true,
      maxRetries: 3,
      retryDelay: 100,
      ...options
    }

    return new Promise((resolve, reject) => {
      try {
        // 验证组件
        if (!this.validateComponent(component)) {
          const error = new Error('组件无效或已销毁')
          this.handleError(component, error, data, config)
          reject(error)
          return
        }

        // 验证数据
        const validData = config.validate ? this.validateData(data) : data
        if (!validData || Object.keys(validData).length === 0) {
          console.warn('setData: 数据为空或无效', data)
          if (callback) callback()
          resolve()
          return
        }

        // 立即执行或批量执行
        if (config.immediate || !config.batch) {
          this.executeSetData(component, validData, callback, config)
            .then(resolve)
            .catch(reject)
        } else {
          this.addToBatch(component, validData, callback, config, resolve, reject)
        }

      } catch (error) {
        this.handleError(component, error, data, config)
        reject(error)
      }
    })
  }

  /**
   * 执行 setData
   * @param {Object} component - 组件实例
   * @param {Object} data - 数据
   * @param {Function} callback - 回调
   * @param {Object} config - 配置
   * @param {number} retryCount - 重试次数
   */
  async executeSetData(component, data, callback, config, retryCount = 0) {
    try {
      // 再次验证组件状态
      if (!this.validateComponent(component)) {
        throw new Error('组件在执行前已销毁')
      }

      // 创建安全的回调
      const safeCallback = () => {
        try {
          if (this.validateComponent(component) && callback) {
            callback()
          }
        } catch (callbackError) {
          console.error('setData 回调执行失败:', callbackError)
        }
      }

      // 执行 setData
      await this.performSetData(component, data, safeCallback)

    } catch (error) {
      // 检查是否为32776错误
      if (this.is32776Error(error)) {
        errorMonitoring.logTextUpdateError('TEXT_UPDATE_32776', error, {
          component,
          data,
          retryCount,
          retryCallback: () => this.executeSetData(component, data, callback, config, retryCount + 1)
        })
      }

      // 重试逻辑
      if (config.retry && retryCount < config.maxRetries) {
        console.warn(`setData 失败，第 ${retryCount + 1} 次重试:`, error.message)
        
        const delay = config.retryDelay * Math.pow(2, retryCount)
        await this.delay(delay)
        
        if (this.validateComponent(component)) {
          return this.executeSetData(component, data, callback, config, retryCount + 1)
        }
      }

      throw error
    }
  }

  /**
   * 实际执行 setData
   * @param {Object} component - 组件实例
   * @param {Object} data - 数据
   * @param {Function} callback - 回调
   */
  performSetData(component, data, callback) {
    return new Promise((resolve, reject) => {
      try {
        // 使用 setTimeout 确保在下一个事件循环中执行
        setTimeout(() => {
          try {
            if (!this.validateComponent(component)) {
              reject(new Error('组件在执行时已销毁'))
              return
            }

            component.setData(data, () => {
              try {
                if (callback) callback()
                resolve()
              } catch (callbackError) {
                console.error('setData 回调错误:', callbackError)
                resolve() // 即使回调失败，setData 本身是成功的
              }
            })
          } catch (setDataError) {
            reject(setDataError)
          }
        }, 0)
      } catch (error) {
        reject(error)
      }
    })
  }

  /**
   * 添加到批量更新队列
   * @param {Object} component - 组件实例
   * @param {Object} data - 数据
   * @param {Function} callback - 回调
   * @param {Object} config - 配置
   * @param {Function} resolve - Promise resolve
   * @param {Function} reject - Promise reject
   */
  addToBatch(component, data, callback, config, resolve, reject) {
    const componentId = this.getComponentId(component)
    
    if (!this.updateQueue.has(componentId)) {
      this.updateQueue.set(componentId, {
        component,
        updates: [],
        callbacks: [],
        resolvers: [],
        rejectors: []
      })
    }

    const batch = this.updateQueue.get(componentId)
    batch.updates.push(data)
    batch.callbacks.push(callback)
    batch.resolvers.push(resolve)
    batch.rejectors.push(reject)

    // 如果批量大小达到限制，立即执行
    if (batch.updates.length >= this.maxBatchSize) {
      this.processBatch(componentId)
    } else {
      // 否则延迟执行
      this.scheduleBatchProcess()
    }
  }

  /**
   * 调度批量处理
   */
  scheduleBatchProcess() {
    if (this.batchTimeout) {
      clearTimeout(this.batchTimeout)
    }

    this.batchTimeout = setTimeout(() => {
      this.processAllBatches()
    }, this.batchDelay)
  }

  /**
   * 处理所有批量更新
   */
  async processAllBatches() {
    if (this.isProcessing) return
    
    this.isProcessing = true
    
    try {
      const componentIds = Array.from(this.updateQueue.keys())
      
      for (const componentId of componentIds) {
        await this.processBatch(componentId)
      }
    } finally {
      this.isProcessing = false
    }
  }

  /**
   * 处理单个组件的批量更新
   * @param {string} componentId - 组件ID
   */
  async processBatch(componentId) {
    const batch = this.updateQueue.get(componentId)
    if (!batch || batch.updates.length === 0) return

    const { component, updates, callbacks, resolvers, rejectors } = batch
    
    // 清空队列
    this.updateQueue.delete(componentId)

    try {
      // 验证组件
      if (!this.validateComponent(component)) {
        const error = new Error('批量更新时组件已销毁')
        rejectors.forEach(reject => reject(error))
        return
      }

      // 合并所有更新
      const mergedData = this.mergeUpdates(updates)
      
      // 合并所有回调
      const mergedCallback = () => {
        callbacks.forEach(callback => {
          if (callback && typeof callback === 'function') {
            try {
              callback()
            } catch (error) {
              console.error('批量回调执行失败:', error)
            }
          }
        })
      }

      // 执行合并后的更新
      await this.executeSetData(component, mergedData, mergedCallback, { 
        immediate: true, 
        batch: false, 
        retry: true 
      })

      // 解决所有 Promise
      resolvers.forEach(resolve => resolve())

    } catch (error) {
      console.error('批量更新失败:', error)
      rejectors.forEach(reject => reject(error))
    }
  }

  /**
   * 合并多个更新对象
   * @param {Array} updates - 更新数组
   * @returns {Object} 合并后的数据
   */
  mergeUpdates(updates) {
    const merged = {}
    
    updates.forEach(update => {
      Object.keys(update).forEach(key => {
        // 后面的更新覆盖前面的
        merged[key] = update[key]
      })
    })

    return merged
  }

  /**
   * 验证组件
   * @param {Object} component - 组件实例
   * @returns {boolean}
   */
  validateComponent(component) {
    if (!component) return false

    // 检查基本属性
    if (typeof component.setData !== 'function') return false
    if (component.data === undefined) return false

    // 检查生命周期管理器中的状态
    const componentId = this.getComponentId(component)
    if (lifecycleManager.isDestroyed(componentId)) return false

    // 检查微信小程序特有属性
    try {
      // 尝试访问 data 属性，如果组件已销毁会抛出错误
      const testData = component.data
      return testData !== undefined
    } catch (error) {
      return false
    }
  }

  /**
   * 验证数据
   * @param {Object} data - 要验证的数据
   * @returns {Object} 验证后的数据
   */
  validateData(data) {
    if (!data || typeof data !== 'object') return {}

    const validData = {}
    
    Object.keys(data).forEach(key => {
      const value = data[key]
      
      // 跳过 undefined 值
      if (value === undefined) return
      
      // 处理 null 值
      if (value === null) {
        validData[key] = ''
        return
      }

      // 验证键名
      if (!this.isValidKey(key)) {
        console.warn(`无效的数据键: ${key}`)
        return
      }

      // 验证值
      if (this.isValidValue(value)) {
        validData[key] = value
      } else {
        console.warn(`无效的数据值: ${key} = ${value}`)
      }
    })

    return validData
  }

  /**
   * 验证键名
   * @param {string} key - 键名
   * @returns {boolean}
   */
  isValidKey(key) {
    if (typeof key !== 'string') return false
    if (key.length === 0) return false
    if (key.startsWith('_')) return false // 私有属性
    return true
  }

  /**
   * 验证值
   * @param {*} value - 值
   * @returns {boolean}
   */
  isValidValue(value) {
    // 基本类型
    if (typeof value === 'string' || 
        typeof value === 'number' || 
        typeof value === 'boolean') {
      return true
    }

    // 数组和对象
    if (Array.isArray(value) || 
        (typeof value === 'object' && value !== null)) {
      try {
        // 尝试序列化，检查是否包含循环引用
        JSON.stringify(value)
        return true
      } catch (error) {
        return false
      }
    }

    return false
  }

  /**
   * 检查是否为32776错误
   * @param {Error} error - 错误对象
   * @returns {boolean}
   */
  is32776Error(error) {
    return error && error.message && error.message.includes('32776')
  }

  /**
   * 处理错误
   * @param {Object} component - 组件实例
   * @param {Error} error - 错误对象
   * @param {Object} data - 原始数据
   * @param {Object} config - 配置
   */
  handleError(component, error, data, config) {
    const context = {
      component,
      componentId: this.getComponentId(component),
      data,
      config,
      timestamp: Date.now()
    }

    if (this.is32776Error(error)) {
      errorMonitoring.logTextUpdateError('TEXT_UPDATE_32776', error, context)
    } else {
      errorMonitoring.logTextUpdateError('SETDATA_ERROR', error, context)
    }
  }

  /**
   * 获取组件ID
   * @param {Object} component - 组件实例
   * @returns {string}
   */
  getComponentId(component) {
    if (component.__wxExparserNodeId__) {
      return `wx_${component.__wxExparserNodeId__}`
    }
    if (component.route) {
      return `page_${component.route}`
    }
    if (component.is) {
      return `component_${component.is}`
    }
    return `unknown_${Date.now()}`
  }

  /**
   * 延迟函数
   * @param {number} ms - 延迟毫秒数
   * @returns {Promise}
   */
  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
  }

  /**
   * 清理组件的待处理更新
   * @param {string} componentId - 组件ID
   */
  clearPendingUpdates(componentId) {
    const batch = this.updateQueue.get(componentId)
    if (batch) {
      // 拒绝所有待处理的 Promise
      batch.rejectors.forEach(reject => {
        reject(new Error('组件已销毁，取消待处理更新'))
      })
      
      this.updateQueue.delete(componentId)
    }
  }

  /**
   * 获取统计信息
   * @returns {Object}
   */
  getStats() {
    return {
      pendingBatches: this.updateQueue.size,
      isProcessing: this.isProcessing,
      totalPendingUpdates: Array.from(this.updateQueue.values())
        .reduce((total, batch) => total + batch.updates.length, 0)
    }
  }
}

// 创建全局实例
const safeSetData = new SafeSetDataWrapper()

// 导出便捷方法
export const setData = (component, data, callback, options) => {
  return safeSetData.safeSetData(component, data, callback, options)
}

export const setDataImmediate = (component, data, callback) => {
  return safeSetData.safeSetData(component, data, callback, { immediate: true })
}

export const setDataBatch = (component, data, callback) => {
  return safeSetData.safeSetData(component, data, callback, { batch: true })
}

export const clearPendingUpdates = (componentId) => {
  return safeSetData.clearPendingUpdates(componentId)
}

export default safeSetData